#include <avr/io.h>

const long X = 3; //for demo purpose, increasing x, results in reducing the frequency of changes in projects setup
const long interval = 3000/X; //in microseconds.

int transmitDelayMicro = 100;

#define PSCK 0
#define PDATA 1

const int SCK = 8;
const int DATA = 9;

const int channelNumber = 96;
int channels[channelNumber];

uint8_t rxBuffer[3];
uint8_t rxCount = 0; 

void transmitDelay(){
  if(transmitDelayMicro >= 1000){
    delay(transmitDelayMicro/1000);    
  } 
  else {
    delayMicroseconds(transmitDelayMicro);
  }
}

void sendBit(boolean b){
  PORTB &= ~_BV(PSCK);
  //digitalWrite(SCK, LOW);
  transmitDelay();
  if(b){
     PORTB |= _BV(PDATA); 
  } else {
     PORTB &= ~_BV(PDATA);
  }
  //digitalWrite(DATA, b);
  transmitDelay();
  PORTB |= _BV(PSCK);
  //digitalWrite(SCK, HIGH);
  transmitDelay();
}

void sendSync(){
  for(int i=0;i<16;++i){
    sendBit(LOW);
  }
}

void sendChannel(int g){
  sendBit(HIGH);
  sendBit(LOW);
  int mask = 0x80;
  for(;mask>=0x04;mask>>=1){
    if(g & mask){
      sendBit(HIGH);
    } 
    else{
      sendBit(LOW);
    }
  }
  sendBit(HIGH);
  for(;mask>0;mask>>=1){
    if(g & mask){
      sendBit(HIGH);
    }
    else{
      sendBit(LOW);
    }
  }
  for(mask=0x80;mask>0x04;mask>>=1){
    if(channels[g] & mask){
      sendBit(HIGH);
    }
    else{
      sendBit(LOW);
    }
  }
}

void sendTerminator(){
    for(int i=0;i<8;++i){
    sendBit(HIGH);
  }
}

int channel_it = 0;

//send message to devices
void send(){
  sendSync();
  for(int i = 0; i < 4; ++i){
    sendChannel(channel_it);
    channel_it = (++channel_it) % channelNumber; 
  }
  sendTerminator();
}

// Set leds value in ***PROGRAM**
void set(int addr, int power){
  channels[addr]=power;
}

void setupChannels(){
  for(int i=0;i<channelNumber;++i) {
    channels[i] = 0;
  }
}

void setup() {
  pinMode(SCK, OUTPUT); 
  pinMode(DATA, OUTPUT); 

  // Initiate Serial Communication
  Serial.begin(19200); 
  for(int i=8;i<14;++i){
    pinMode(i, OUTPUT);
  }
  setupChannels();
}

void loop() {
  /*
  while(Serial.available()){
      message.process(Serial.read());
  }
  */
  while(Serial.available() > 0){
    rxBuffer[rxCount++] = Serial.read();
    Serial.print(rxBuffer[rxCount-1], DEC);
    if(rxBuffer[rxCount-1] == 255) {
      if(rxCount == 3){
        uint8_t addr = rxBuffer[0];
        uint8_t power = rxBuffer[1];
        set(addr, power);
        sendSync();
        sendChannel(addr);
        sendTerminator();
      }
      rxCount = 0;
    }
  }
  send();
}


